use std::{collections::HashMap, sync::Mutex};

use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
use reqwest::{header, Client};

struct AppData {
    app_name: String,
    req_cnt: Mutex<i32>
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let app_data = web::Data::new(AppData {
        app_name: String::from("actix-demo-service"),
        req_cnt: Mutex::new(0),
    });
    HttpServer::new(move || {
        App::new().service(
            web::scope("/actix-demo")
                .app_data(app_data.clone())
                .service(hello)
                .service(echo)
                .service(reqwest_demo)
                .route("/manual_hello", web::get().to(manual_hello)),
        )
    })
    .bind(("127.0.0.1", 8081))?
    .run()
    .await
}

#[get("/hello")]
async fn hello(app_data: web::Data<AppData>) -> impl Responder {
    let mut req_cnt = app_data.req_cnt.lock().unwrap();
    *req_cnt += 1;
    println!("debug: app_name={}, request count={}", &app_data.app_name, req_cnt);
    let intro = format!("Hello World!.{}", &app_data.app_name);
    println!("debug: intro={intro}");
    HttpResponse::Ok().body(intro)
}

#[post("/echo")]
async fn echo(request_body: String) -> impl Responder {
    HttpResponse::Ok().body(request_body)
}

#[get("/reqwest")]
async fn reqwest_demo() -> impl Responder {
    HttpResponse::Ok().body(test_req().await.expect(""))
}

async fn test_req() -> Result<String, Box<dyn std::error::Error>> {
    let client = reqwest::Client::new();
    let body = client.get("http://httpbin.org/get")
            // set query params
        .send()
        .await?
        .text()
        .await?;
    println!("{body}");
    Ok(body)
}

async fn manual_hello() -> impl Responder {
    HttpResponse::Ok().body("Manual Hello World!")
}
